﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using Flame.Dlr;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
//using System.Windows.Forms.Integration;
using System.Windows;
using Microsoft.CSharp.RuntimeBinder;

namespace Flame.Controls
{
    internal class RichOutputCompiler : Panel, IOutput
    {
        #region Private
        const int IntraLineDistance = 1;

        void clear()
        {
            ContentHeight = 0;
            Controls.Clear();
        }

        #endregion

        int _heightSaved = 0;

        public RichOutputCompiler()
        {
            BorderStyle = System.Windows.Forms.BorderStyle.None;
            BackColor = Color.GhostWhite;
        }

        public void SetParent(Panel panel)
        {
            Dock = DockStyle.Fill;
            panel.Controls.Add(this);
        }


        void addToPanel(Control p, Control c)
        {
            try
            {
                p.Controls.Add(c);
            }
            catch (Exception e)
            {
                p.Controls.Add(ControlConverter.GetControl(e)[0][0]);
            }
            p.Height = c.Height;
        }

        void clicked()
        {
            
        }

        Control layoutHorizontalControl(List<Control> controls)
        {
            Control p = new Control();
            int w = 0;
            foreach (Control c in controls)
            {
                c.Location = new System.Drawing.Point(w, 0);
                addToPanel(p, c);
                w += c.Width;
                
                /*c.MouseDown += (s, e) => 
                {
                    if (e.Button == System.Windows.Forms.MouseButtons.Middle)
                    {
                        if (Height == 10) this.Height = _heightSaved;
                        if (Height != 10) this.Height = 10;
                    }
                };*/
            }
            p.Width = w;
            return p;
        }

        /*bool _circular(Control p1, Control p2)
        {
            foreach (Control c in p2.Controls)
            {
                if (p1 == c) return true;
                if (_circular(p1, c)) return true;
            }
            return false;
        }

        bool circular(Control p1, Control p2)
        {
            if (_circular(p1, p2)) return true;
            if (_circular(p2, p1)) return true;
            return false;
        }*/

        bool _circular(Control p1, Control p2)
        {

            if (p2 == null) return false;
            if (p1 == p2) return true;

            if (_circular(p1, p2.Parent)) return true;
           
            return false;
        }

        bool circular(Control f, List<List<Control>> controls)
        {
            foreach (List<Control> cs in controls)
            {
                foreach (Control c in cs)
                {
                    if (_circular(c, f)) return true;
                }
            }
            return false;
        }

        Control layoutControl(List<List<Control>> controls)
        {
            if (!circular(this, controls))
            {
                Control p = new Control();
                p.Width = 0;

                int h = 0;
                foreach (List<Control> controls2 in controls)
                {
                    Control pt = layoutHorizontalControl(controls2);
                    pt.Location = new System.Drawing.Point(0, h);
                    p.Width = Math.Max(p.Width, pt.Width);
                    addToPanel(p, pt);
                    h += pt.Height;
                }
                p.Height = h;

                Controls.Add(p);

                ContentHeight = p.Height;
                Height = p.Height;
                Width = p.Width;
                _heightSaved = Height;
                return p;
            }
            else
            {
                return layoutControl(new List<List<Control>> { new List<Control> { ControlConverter.Get(new FlameException("A circular control reference has been made. A control cannot be owned by or parented to itself")) } });
                //return ControlConverter.Get(e);
            }
        }

        public TextCompilerResult Set(Result compilerResult)
        {
            clear();
            List<List<Control>> c = ControlConverter.GetControl(compilerResult.Data);
            
            
            return new TextCompilerResult() { Height = layoutControl(c).Height };
        }

        public MemoryStream ToMemoryStream(int n) { return new MemoryStream(); }
        public void FromStream(Stream ms, int n) { }

        public int ContentHeight { get; private set; }


        public void Clear()
        {
            clear();
            ContentHeight = 0;
            Height = ContentHeight;
        }
    }
}
